include("./XPath_server");

var DOM = require("./dom");
var parser = new DOM.DOMParser();
var serializer = new DOM.XMLSerializer();
exports.parser = parser;
exports.serializer = serializer;
exports.document = new DOM.Document();
var xPathEvaluator = new XPathEvaluator();

var logger = require("./logger").logger;


var selectElements = function (root, path) {
	if (root.nodeName == 'HYPERNODE') {
		return remoteSelectElements(root, path);
	}
	
	logger.log("[DAVE] selectElements begin root="+ root + " path=" + path + " \n");
	var xPathRes = xPathEvaluator.evaluate( path, root, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
	
	var array = new Array(xPathRes.snapshotLength);
	for (i=0; i<xPathRes.snapshotLength; i++) {
		logger.log("[DAVE] selectElements element index=" + i + " node=" + xPathRes.snapshotItem(i) + "\n");
		if (xPathRes.snapshotItem(i).nodeType == DOM.Node.ELEMENT_NODE) {
			
			array[i] = xPathRes.snapshotItem(i);
			
		}
	}
	
	logger.log("[DAVE] selectElements end \n");
	
	return array;
};


var selectAttributes = function (root, path) {
	if (root.nodeName == 'HYPERNODE') {
		return remoteSelectAttributes(root, path);
	}

	var elems = selectElements(root, path);

	var array = new Array(elems.length);
	
	for (i=0; i<elems.length; i++) {
	
		var map = new Object();
		
		if (elems[i].nodeType == DOM.Node.ELEMENT_NODE) {
			for (j=0; j<elems[i].attributes.length; j++) {
				 map[elems[i].attributes[j].nodeName] = elems[i].attributes[j].nodeValue;
			}
		}
		
		array[i] = map;
	}
	
	return array;
};

var selectContents = function (root, path) {
	if (root.nodeName == 'HYPERNODE') {
		return remoteSelectContents(root, path);
	}

	logger.log("[DAVE] selectContents begin root="+ root + " path=" + path + " \n");
	
	var elems = selectElements(root, path);
	
	var array = new Array(elems.length);
	
	for (i=0; i<elems.length; i++) {
		logger.log("[DAVE] selectContents element index=" + i + " node=" + elems[i] + "\n");
		if (elems[i].nodeType == DOM.Node.ELEMENT_NODE) {
			array[i] = serializer._serializeChildNodes(elems[i], 0);
		}
		
	}
	
	logger.log("[DAVE] selectContents end \n");
	
	return array;
};

var setAttributes = function (root, path, attributes) {
	if (typeof attributes != "object") return false;
	
	if (root.nodeName == 'HYPERNODE') {
		return remoteSetAttributes(root, path);
	}

	var elems = selectElements(root, path);
	
	for (i=0; i<elems.length; i++) {
	
		if (elems[i].nodeType == DOM.Node.ELEMENT_NODE) {
		
			for (var j in attributes) {
			
				//TODO fire event (manually or implementing mechanism in dom.js)
				/*
					var eventObject = document.createEvent('MutationEvent');
					var attrChange;
					if (elems[i].hasAttribute(j)) {
						attrChange = MutationEvent.MODIFICATION;
					} else {
						attrChange = MutationEvent.ADDITION;
					}
					eventObject.initMutationEvent ("DOMAttrModified", false, true, attributes[j], elems[i].getAttribute(j), attributes[j], j, attrChange);
					elems[i].dispatchEvent(eventObject);
				*/
				elems[i].setAttribute(j, attributes[j]);
			}
			
		}
		
	}
	
	return true;
};

var setContent = function (root, path, content) {
	if (typeof content != "string") return false;
	
	if (root.nodeName == 'HYPERNODE') {
		return remoteSetContent(root, path, content);
	}
	
	var elems = selectElements(root, path);
	
	var doc = parser.parseFromString(content);
	for (i=0; i<elems.length; i++) {
		
		if (elems[i].nodeType == DOM.Node.ELEMENT_NODE) {
	
			elems[i].childNodes = [];
		
			for (j=0; j<doc.childNodes.length; j++) {
			
				//TODO fire event (manually or implementing mechanism in dom.js)
				/*
					var eventObject = document.createEvent('MutationEvent');
					eventObject.initMutationEvent ("DOMContentModified", true, true, elems[i], elems[i].innerHTML, newContent, null, MutationEvent.MODIFICATION);
					elems[i].dispatchEvent(eventObject);
				*/
					
				elems[i].appendChild(doc.childNodes[j]);
		
			}
			
		}
	}
	
	return true;
};

var removeElements = function (root, path) {
	if (root.nodeName == 'HYPERNODE') {
		return remoteRemoveElements(root, path);
	}
	
	var elems = selectElements(root, path);
	
	for (i=0; i<elems.length; i++) {
		if (elems[i].nodeType == DOM.Node.ELEMENT_NODE) {
			elems[i].parentNode.removeChild(elems[i]);
		}
	}
	
	return true;
};

var registerEventListener = function (root, path, eventType, fun) {
	if (root.nodeName == 'HYPERNODE') {
		return remoteRegisterEventListener(root, path);
	}

	var elems = selectElements(root, path);
	
	for (i=0; i<elems.length; i++) {
		if (elems[i].nodeType == DOM.Node.ELEMENT_NODE) {
		
		elems[i].addEventListener(eventType, fun);
			
		}
	}
	
	return true;
};

var unregisterEventListener = function (root, path, eventType, fun) {
	if (root.nodeName == 'HYPERNODE') {
		return remoteUnregisterEventListener(root, path);
	}
	
	var elems = selectElements(root, path);
	
	for (i=0; i<elems.length; i++) {
		if (elems[i].nodeType == DOM.Node.ELEMENT_NODE) {
		
			elems[i].removeEventListener(eventType, fun);
			
		}
	}
};

var registerClientEventListener = function (root, path, eventType, funID, clientID) {

	logger.log("[DAVE] registerClientEventListener begin root="+ root + " path=" + path + " eventType="+ eventType+ " funID="+funID+" clientID="+clientID+" \n");

	var elems = selectElements(root, path);
	
	for (i=0; i<elems.length; i++) {
		logger.log("[DAVE] registerClientEventListener element root="+ root + " path=" + path + " funID="+funID+" clientID="+clientID+" \n");
		if (elems[i].nodeType == DOM.Node.ELEMENT_NODE) {
			
			elems[i].addEventListener(eventType, funID, clientID);
			
		}
	}
	
	logger.log("[DAVE] registerClientEventListener end\n");
	
	return true;
};

var unregisterClientEventListener = function (root, path, eventType, funID, clientID) {
	
	var elems = selectElements(root, path);
	
	for (i=0; i<elems.length; i++) {
		if (elems[i].nodeType == DOM.Node.ELEMENT_NODE) {
		
		elems[i].removeEventListener(eventType, funID, clientID);
			
		}
	}
};

var remoteSelectElements = function (root, path) {

	//TODO implement function on session-application layer
};

var remoteSelectAttributes = function (root, path) {

	//TODO implement function on session-application layer
};

var remoteSelectContents = function (root, path) {

	//TODO implement function on session-application layer				 
};

var remoteSetAttributes = function (root, path, attributes) {

	//TODO implement function on session-application layer
};

var remoteSetContent = function (root, path, content) {

	//TODO implement function on session-application layer
};

var remoteRemoveElements = function (root, path) {

	//TODO implement function on session-application layer
};

var remoteRegisterEventListener = function (root, path, eventType, fun) {

	//TODO implement function on session-application layer
};

var remoteUnregisterEventListener = function (root, path, eventType, fun) {

	//TODO implement function on session-application layer
};

exports.selectElements = selectElements;
exports.selectAttributes = selectAttributes;
exports.selectContents = selectContents;
exports.setAttributes = setAttributes;
exports.setContent = setContent;
exports.removeElements = removeElements;
exports.registerEventListener = registerEventListener;
exports.unregisterEventListener = unregisterEventListener;
exports.registerClientEventListener = registerClientEventListener;
exports.unregisterClientEventListener = unregisterClientEventListener;